<!-- uniapp vue2 markdown解析 -->
<template>
	<view class="ua__markdown"><rich-text space="nbsp" :nodes="parseNodes(source)"
			@itemclick="handleItemClick"></rich-text></view>
</template>

<script>
	import MarkdownIt from './lib/markdown-it.min.js'
	import hljs from './lib/highlight/uni-highlight.min.js'
	import './lib/highlight/atom-one-dark.css'
	import parseHtml from './lib/html-parser.js'

	export default {
		name: 'uaMarkdown',
		props: {
			source: String,
			showLine: {
				type: [Boolean, String],
				default: true
			}
		},
		data() {
			return {
				markdown: null,
				copyCodeData: [],
			}
		},
		mounted() {
			let that = this
			let tempData = []
			this.markdown = MarkdownIt({
				html: true,
				highlight: function(str, lang) {
					let preCode = ""
					try {
						preCode = hljs.highlightAuto(str).value
					} catch (err) {
						preCode = that.markdown.utils.escapeHtml(str);
					}
					const lines = preCode.split(/\n/).slice(0, -1)
					// 添加自定义行号
					let html = lines.map((item, index) => {
						if (item == '') {
							return ''
						}
						return '<li><span class="line-num" data-line="' + (index + 1) + '"></span>' +
							item + '</li>'
					}).join('')
					if (that.showLine) {
						html = '<ol style="padding: 0px 30px;">' + html + '</ol>'
					} else {
						html = '<ol style="padding: 0px 7px;list-style:none;">' + html + '</ol>'
					}

					tempData.push(str)
					that.copyCodeData = tempData
					let htmlCode = `<div class="markdown-wrap">`
					// #ifndef MP-WEIXIN
					htmlCode += `<div style="color: #aaa;text-align: right;font-size: 12px;padding:8px;">`
					htmlCode +=
						`${lang}<a class="copy-btn" code-data-index="${tempData.length - 1}" style="margin-left: 8px;">复制代码</a>`
					htmlCode += `</div>`
					// #endif
					htmlCode +=
						`<pre class="hljs" style="padding:10px 8px 0;margin-bottom:5px;overflow: auto;display: block;border-radius: 5px;"><code>${html}</code></pre>`;
					htmlCode += '</div>'
					return htmlCode
				}
			})
		},
		methods: {
			parseNodes(value) {
				if (!value) return
				if (!this.markdown) return
				// 解析<br />到\n
				value = value.replace(/<br>|<br\/>|<br \/>/g, "\n")
				value = value.replace(/&nbsp;/g, " ")
				let htmlString = ''
				if (value.split("```").length % 2) {
					let mdtext = value
					if (mdtext[mdtext.length - 1] != '\n') {
						mdtext += '\n'
					}
					htmlString = this.markdown.render(mdtext)
				} else {
					htmlString = this.markdown.render(value)
				}
				// 解决小程序表格边框型失效问题
				htmlString = htmlString.replace(/<table/g, `<table class="table"`)
				htmlString = htmlString.replace(/<tr/g, `<tr class="tr"`)
				htmlString = htmlString.replace(/<th>/g, `<th class="th">`)
				htmlString = htmlString.replace(/<td/g, `<td class="td"`)
				htmlString = htmlString.replace(/<hr>|<hr\/>|<hr \/>/g, `<hr class="hr">`)

				// #ifndef APP-NVUE
				return htmlString
				// #endif

				// 将htmlString转成htmlArray，反之使用rich-text解析
				// #ifdef APP-NVUE
				return parseHtml(htmlString)
				// #endif
			},
			handleItemClick(e) {
				let {
					attrs
				} = e.detail.node
				let {
					"code-data-index": codeDataIndex,
					"class": className
				} = attrs
				if (className == 'copy-btn') {
					uni.setClipboardData({
						data: this.copyCodeData[codeDataIndex],
						showToast: false,
						success() {
							uni.showToast({
								title: '复制成功',
								icon: 'none'
							});
						}
					})
				}
			}
		}
	}
</script>

<style lang="scss" scoped>
	.ua__markdown {
		font-size: 14px;
		line-height: 1.5;
		word-break: break-all;

		h1,
		h2,
		h3,
		h4,
		h5,
		h6 {
			font-family: inherit;
			font-weight: 500;
			line-height: 1.1;
			color: inherit;
		}

		h1,
		h2,
		h3 {
			margin-top: 20px;
			margin-bottom: 10px
		}

		h4,
		h5,
		h6 {
			margin-top: 10px;
			margin-bottom: 10px
		}

		.h1,
		h1 {
			font-size: 36px
		}

		.h2,
		h2 {
			font-size: 30px
		}

		.h3,
		h3 {
			font-size: 24px
		}

		.h4,
		h4 {
			font-size: 18px
		}

		.h5,
		h5 {
			font-size: 14px
		}

		.h6,
		h6 {
			font-size: 12px
		}

		a {
			background-color: transparent;
			color: #2196f3;
			text-decoration: none;
		}

		hr,
		::v-deep .hr {
			margin-top: 20px;
			margin-bottom: 20px;
			border: 0;
			border-top: 1px solid #e5e5e5;
		}

		img {
			max-width: 35%;
		}

		p {
			margin: 0 0 10px
		}

		em {
			font-style: italic;
			font-weight: inherit;
		}

		ol,
		ul {
			margin-top: 0;
			margin-bottom: 10px;
			padding-left: 40px;
		}

		ol ol,
		ol ul,
		ul ol,
		ul ul {
			margin-bottom: 0;
		}

		ol ol,
		ul ol {
			list-style-type: lower-roman;
		}

		ol ol ol,
		ul ul ol {
			list-style-type: lower-alpha;
		}

		dl {
			margin-top: 0;
			margin-bottom: 20px;
		}

		dt {
			font-weight: 600;
		}

		dt,
		dd {
			line-height: 1.4;
		}

		.task-list-item {
			list-style-type: none;
		}

		.task-list-item input {
			margin: 0 .2em .25em -1.6em;
			vertical-align: middle;
		}

		pre {
			position: relative;
			z-index: 11;
		}

		code,
		kbd,
		pre,
		samp {
			font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
		}

		code:not(.hljs) {
			padding: 2px 4px;
			font-size: 90%;
			color: #c7254e;
			background-color: #ffe7ee;
			border-radius: 4px;
		}

		code:empty {
			display: none;
		}

		pre code.hljs {
			color: var(--vg__text-1);
			border-radius: 16px;
			background: var(--vg__bg-1);
			font-size: 12px;
		}

		.markdown-wrap {
			font-size: 12px;
			margin-bottom: 10px;
		}

		pre.code-block-wrapper {
			background: #2b2b2b;
			color: #f8f8f2;
			border-radius: 4px;
			overflow-x: auto;
			padding: 1em;
			position: relative;
		}

		pre.code-block-wrapper code {
			padding: auto;
			font-size: inherit;
			color: inherit;
			background-color: inherit;
			border-radius: 0;
		}

		.code-block-header__copy {
			font-size: 16px;
			margin-left: 5px;
		}

		abbr[data-original-title],
		abbr[title] {
			cursor: help;
			border-bottom: 1px dotted #777;
		}

		blockquote {
			padding: 10px 20px;
			margin: 0 0 20px;
			font-size: 17.5px;
			border-left: 5px solid #e5e5e5;
		}

		blockquote ol:last-child,
		blockquote p:last-child,
		blockquote ul:last-child {
			margin-bottom: 0
		}

		blockquote .small,
		blockquote footer,
		blockquote small {
			display: block;
			font-size: 80%;
			line-height: 1.42857143;
			color: #777
		}

		blockquote .small:before,
		blockquote footer:before,
		blockquote small:before {
			content: '\2014 \00A0'
		}

		.blockquote-reverse,
		blockquote.pull-right {
			padding-right: 15px;
			padding-left: 0;
			text-align: right;
			border-right: 5px solid #eee;
			border-left: 0
		}

		.blockquote-reverse .small:before,
		.blockquote-reverse footer:before,
		.blockquote-reverse small:before,
		blockquote.pull-right .small:before,
		blockquote.pull-right footer:before,
		blockquote.pull-right small:before {
			content: ''
		}

		.blockquote-reverse .small:after,
		.blockquote-reverse footer:after,
		.blockquote-reverse small:after,
		blockquote.pull-right .small:after,
		blockquote.pull-right footer:after,
		blockquote.pull-right small:after {
			content: '\00A0 \2014'
		}

		.footnotes {
			-moz-column-count: 2;
			-webkit-column-count: 2;
			column-count: 2
		}

		.footnotes-list {
			padding-left: 2em
		}

		table,
		::v-deep .table {
			border-spacing: 0;
			border-collapse: collapse;
			width: 100%;
			max-width: 65em;
			overflow: auto;
			margin-top: 0;
			margin-bottom: 16px;
		}

		table tr,
		::v-deep .table .tr {
			border-top: 1px solid #e5e5e5;
		}

		table th,
		table td,
		::v-deep .table .th,
		::v-deep .table .td {
			padding: 6px 13px;
			border: 1px solid #e5e5e5;
		}

		table th,
		::v-deep .table .th {
			font-weight: 600;
			background-color: #eee;
		}

		.hljs[class*=language-]:before {
			position: absolute;
			z-index: 3;
			top: .8em;
			right: 1em;
			font-size: .8em;
			color: #999;
		}

		.hljs[class~=language-js]:before {
			content: "js"
		}

		.hljs[class~=language-ts]:before {
			content: "ts"
		}

		.hljs[class~=language-html]:before {
			content: "html"
		}

		.hljs[class~=language-md]:before {
			content: "md"
		}

		.hljs[class~=language-vue]:before {
			content: "vue"
		}

		.hljs[class~=language-css]:before {
			content: "css"
		}

		.hljs[class~=language-sass]:before {
			content: "sass"
		}

		.hljs[class~=language-scss]:before {
			content: "scss"
		}

		.hljs[class~=language-less]:before {
			content: "less"
		}

		.hljs[class~=language-stylus]:before {
			content: "stylus"
		}

		.hljs[class~=language-go]:before {
			content: "go"
		}

		.hljs[class~=language-java]:before {
			content: "java"
		}

		.hljs[class~=language-c]:before {
			content: "c"
		}

		.hljs[class~=language-sh]:before {
			content: "sh"
		}

		.hljs[class~=language-yaml]:before {
			content: "yaml"
		}

		.hljs[class~=language-py]:before {
			content: "py"
		}

		.hljs[class~=language-docker]:before {
			content: "docker"
		}

		.hljs[class~=language-dockerfile]:before {
			content: "dockerfile"
		}

		.hljs[class~=language-makefile]:before {
			content: "makefile"
		}

		.hljs[class~=language-javascript]:before {
			content: "js"
		}

		.hljs[class~=language-typescript]:before {
			content: "ts"
		}

		.hljs[class~=language-markup]:before {
			content: "html"
		}

		.hljs[class~=language-markdown]:before {
			content: "md"
		}

		.hljs[class~=language-json]:before {
			content: "json"
		}

		.hljs[class~=language-ruby]:before {
			content: "rb"
		}

		.hljs[class~=language-python]:before {
			content: "py"
		}

		.hljs[class~=language-bash]:before {
			content: "sh"
		}

		.hljs[class~=language-php]:before {
			content: "php"
		}
	}
</style>